package com.ims.core.doc.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ims.common.annotation.RequestParamsSplit;
import com.ims.common.core.domain.entity.SysUser;
import com.ims.common.exception.ServiceException;
import com.ims.common.exception.base.BaseException;
import com.ims.common.utils.DateUtils;
import com.ims.common.utils.DictUtils;
import com.ims.common.utils.SecurityUtils;
import com.ims.common.utils.uuid.IdUtils;
import com.ims.core.doc.domain.*;
import com.ims.core.doc.mapper.TScSettleSalInvoiceMapper;
import com.ims.core.doc.service.ITSalInvoiceService;
import com.ims.core.doc.service.ITScSettleSalInvoiceService;
import com.ims.core.enums.*;
import com.ims.core.erp.ErpApiUtil;
import com.ims.core.saleconfig.domain.TSalBuyer;
import com.ims.core.saleconfig.service.ITSalBuyerService;
import com.ims.system.domain.TSysSite;
import com.ims.system.service.ITSysSiteService;
import org.apache.poi.ss.formula.functions.T;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ims.common.utils.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import com.ims.core.doc.mapper.TScSettlebillMapper;
import com.ims.core.doc.service.ITScSettlebillService;
import org.springframework.util.CollectionUtils;

/**
 * 结算单Service业务层处理
 *
 * @author IMS
 * @date 2024-05-30
 */
@Service
public class TScSettlebillServiceImpl implements ITScSettlebillService
{
    private static final Logger logger = LoggerFactory.getLogger(TScSettlebillServiceImpl.class);

    @Autowired
    private TScSettlebillMapper tScSettlebillMapper;

    @Autowired
    private ITSalInvoiceService tSalInvoiceService;

    @Autowired
    private ITScSettleSalInvoiceService tScSettleSalInvoiceService;

    @Autowired
    private ITSalBuyerService tSalBuyerService;

    @Autowired
    private ITSysSiteService tSysSiteService;

    /**
     * 查询结算单
     *
     * @param id 结算单主键
     * @return 结算单
     */
    @Override
    public TScSettlebill selectTScSettlebillById(Long id)
    {
        return tScSettlebillMapper.selectTScSettlebillById(id);
    }

    @Override
    public TScSettlebill selectTScSettlebillBySettleId(String settleId) {
        TScSettlebill tScSettlebillCondition = new TScSettlebill();
        tScSettlebillCondition.setSettleId(settleId);
        List<TScSettlebill> tScSettlebillList = tScSettlebillMapper.selectTScSettlebillList(tScSettlebillCondition);
        if(CollectionUtils.isEmpty(tScSettlebillList)){
            return null;
        }
        return tScSettlebillList.get(0);
    }

    @Override
    public TScSettlebill selectTScSettlebillByIdForInvoice(Long id) {
        TScSettlebill tScSettlebill = tScSettlebillMapper.selectTScSettlebillById(id);
        // 查询剩余可开票明细
        List<TScSettlebillEntryForinvoice> lastTScSettlebillEntryForinvoiceList = tScSettlebillMapper.selectLastTScSettlebillEntryForinvoiceList(tScSettlebill.getSettleId());
        // 第一次开票时，可开票明细项为空，直接返回原明细
        if(CollectionUtils.isEmpty(lastTScSettlebillEntryForinvoiceList)){
            return tScSettlebill;
        }
        List<TScSettlebillEntry> tScSettlebillEntryList = new ArrayList<>();
        for(TScSettlebillEntryForinvoice tScSettlebillEntryForinvoice : lastTScSettlebillEntryForinvoiceList){
            TScSettlebillEntry tScSettlebillEntry = new TScSettlebillEntry();
            BeanUtils.copyProperties(tScSettlebillEntryForinvoice, tScSettlebillEntry);
            tScSettlebillEntryList.add(tScSettlebillEntry);
        }
        tScSettlebill.setTScSettlebillEntryList(tScSettlebillEntryList);
        return tScSettlebill;
    }

    @Override
    public TScSettlebill selectTScSettlebillByIdForMergeInvoice(Long[] ids) {
        // 1. 校验这批结算的是否可合并
        List<TScSettlebill> tScSettlebillList = tScSettlebillMapper.selectTScSettlebillByIds(ids);
        String invoiceType = tScSettlebillList.get(0).getInvoiceType();
        String buyerName = tScSettlebillList.get(0).getBuyerName();
        String buyerNumber = tScSettlebillList.get(0).getBuyerNumber();
        String buyerBank = tScSettlebillList.get(0).getBuyerBank();
        String buyerAccount = tScSettlebillList.get(0).getBuyerAccount();
        String invoiceName = tScSettlebillList.get(0).getInvoiceName();

        // 总剩余开票金额
        String totalSettleId = "";
        String totalOrderId = "";
        String totalOrderNo = "";
        BigDecimal totalPendingFee = BigDecimal.ZERO;
        for(TScSettlebill tScSettlebill : tScSettlebillList){
            if(
                    !invoiceType.equals(tScSettlebill.getInvoiceType()) ||
                    !buyerName.equals(tScSettlebill.getBuyerName()) ||
                    !buyerNumber.equals(tScSettlebill.getBuyerNumber()) ||
                    !buyerBank.equals(tScSettlebill.getBuyerBank()) ||
                    !buyerAccount.equals(tScSettlebill.getBuyerAccount()) ||
                    !invoiceName.equals(tScSettlebill.getInvoiceName())
            ){
                throw new ServiceException("合并开票需要保证 发票类型、购方和开票人信息一致");
            }
            if(tScSettlebill.getSettlebillStatus().equals(SettlebillStatus.COMPLETED)){
                throw new ServiceException("结算单" + tScSettlebill.getOrderNo() + "已" + DictUtils.getDictLabel("settlebill_status", tScSettlebill.getSettlebillStatus()+""));
            }
            totalPendingFee = totalPendingFee.add(tScSettlebill.getPendingFee());
            totalSettleId += tScSettlebill.getSettleId() + ",";
            totalOrderId += tScSettlebill.getOrderId() + ",";
            totalOrderNo += tScSettlebill.getOrderNo() + ",";
        }
        // 2. 生成一个虚拟的结算单，去除单号等信息
        TScSettlebill tScSettlebill = new TScSettlebill();
        BeanUtils.copyProperties(tScSettlebillList.get(0), tScSettlebill);
        tScSettlebill.setSettleId(totalSettleId);
        tScSettlebill.setOrderId(totalOrderId);
        tScSettlebill.setOrderNo(totalOrderNo);
        tScSettlebill.setPendingFee(totalPendingFee);

        // 3. 查询这批结算的可开票明细，并合并物料
        tScSettlebill.setTScSettlebillEntryList(tScSettlebillMapper.selectMergeTScSettlebillList(ids));

        // 4. 返回
        return tScSettlebill;
    }

    /**
     * 查询结算单列表
     *
     * @param tScSettlebill 结算单
     * @return 结算单
     */
    @Override
    @RequestParamsSplit
    public List<TScSettlebill> selectTScSettlebillList(TScSettlebill tScSettlebill)
    {
        // 解析查询参数
        return tScSettlebillMapper.selectTScSettlebillList(tScSettlebill);
    }

    /**
     * 新增结算单
     *
     * @param tScSettlebill 结算单
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int insertTScSettlebill(TScSettlebill tScSettlebill)
    {
        tScSettlebill.setSettleId(IdUtils.simpleUUID());
        tScSettlebill.setCreateTime(DateUtils.getNowDate());
        // 没有明细的结算单，业务类型设置为2
        if(CollectionUtils.isEmpty(tScSettlebill.getTScSettlebillEntryList())){
            tScSettlebill.setType("2");
        } else {
            tScSettlebill.setType("1");
        }
        int rows = tScSettlebillMapper.insertTScSettlebill(tScSettlebill);
        insertTScSettlebillEntry(tScSettlebill);
        return rows;
    }

    /**
     * 修改结算单
     *
     * @param tScSettlebill 结算单
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateTScSettlebill(TScSettlebill tScSettlebill)
    {
        tScSettlebill.setUpdateTime(DateUtils.getNowDate());
        tScSettlebillMapper.deleteTScSettlebillEntryBySettleId(tScSettlebill.getSettleId());
        insertTScSettlebillEntry(tScSettlebill);
//        // 没有明细的结算单，业务类型设置为2
//        if(CollectionUtils.isEmpty(tScSettlebill.getTScSettlebillEntryList())){
//            tScSettlebill.setType("2");
//        } else {
//            tScSettlebill.setType("1");
//        }
        return tScSettlebillMapper.updateTScSettlebill(tScSettlebill);
    }

    /**
     * 修改结算单(仅头部)
     *
     * @param tScSettlebill 结算单
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateTScSettlebillOnly(TScSettlebill tScSettlebill)
    {
        tScSettlebill.setUpdateTime(DateUtils.getNowDate());
        return tScSettlebillMapper.updateTScSettlebill(tScSettlebill);
    }

    /**
     * 修改结算单
     *
     * @param tScSettlebill 结算单
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateTScSettlebillForErp(TScSettlebill tScSettlebill)
    {
        tScSettlebill.setUpdateTime(DateUtils.getNowDate());
        tScSettlebillMapper.deleteTScSettlebillEntryBySettleId(tScSettlebill.getSettleId());
        insertTScSettlebillEntry(tScSettlebill);
        // 没有明细的结算单，业务类型设置为2
        if(CollectionUtils.isEmpty(tScSettlebill.getTScSettlebillEntryList())){
            tScSettlebill.setType("2");
        } else {
            tScSettlebill.setType("1");
        }
        return tScSettlebillMapper.updateTScSettlebill(tScSettlebill);
    }

    /**
     * 批量删除结算单
     *
     * @param ids 需要删除的结算单主键
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteTScSettlebillByIds(Long[] ids)
    {
        tScSettlebillMapper.deleteTScSettlebillEntryBySettleIds(ids);
        return tScSettlebillMapper.deleteTScSettlebillByIds(ids);
    }

    @Override
    public void createInvoiceBySettlebillIds(Long[] ids) {
//        for(Long id : ids){
//            TScSettlebill tScSettlebill  = tScSettlebillMapper.selectTScSettlebillById(id);
//            if(!tScSettlebill.getSettlebillStatus().equals(SettlebillStatus.NOT_INVOICED.getCode())
//            ){
//                throw new ServiceException("结算单" + tScSettlebill.getOrderNo() + "已" + DictUtils.getDictLabel("settlebill_status", tScSettlebill.getSettlebillStatus()+""));
//            }
//            // 创建发票对象
//            TSalInvoice tSalInvoice = tSalInvoiceService.createTSalInvoiceByTScSettlebill(tScSettlebill);
//            logger.info("结算单" + tScSettlebill.getOrderNo() + "生成待开发票，申请单号" + tSalInvoice.getApplyNo());
//
//            // 结算单设置为待开票
//            tScSettlebill.setSettlebillStatus(SettlebillStatus.WAITING_FOR_INVOICING.getCode());
//            tScSettlebill.setSettlebillStatusName(SettlebillStatus.WAITING_FOR_INVOICING.getName());
//
//            //提交人
//            SysUser user = SecurityUtils.getLoginUser().getUser();
//            tScSettlebill.setUpdateBy(user.getUserName());
//            tScSettlebill.setUpdateTime(DateUtils.getNowDate());
//            tScSettlebillMapper.updateTScSettlebill(tScSettlebill);
//        }
    }

    /**
     * 删除结算单信息
     *
     * @param id 结算单主键
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteTScSettlebillById(Long id)
    {
        TScSettlebill tScSettlebill = selectTScSettlebillById(id);
        tScSettlebillMapper.deleteTScSettlebillEntryBySettleId(tScSettlebill.getSettleId());
        return tScSettlebillMapper.deleteTScSettlebillById(id);
    }

    /**
     * 新增结算单明细项信息
     *
     * @param tScSettlebill 结算单对象
     */
    public void insertTScSettlebillEntry(TScSettlebill tScSettlebill)
    {
        List<TScSettlebillEntry> tScSettlebillEntryList = tScSettlebill.getTScSettlebillEntryList();
        String settleId = tScSettlebill.getSettleId();
        if (StringUtils.isNotNull(tScSettlebillEntryList))
        {
            List<TScSettlebillEntry> list = new ArrayList<TScSettlebillEntry>();
            for (TScSettlebillEntry tScSettlebillEntry : tScSettlebillEntryList)
            {
                tScSettlebillEntry.setSettleId(settleId);
                list.add(tScSettlebillEntry);
            }
            if (list.size() > 0)
            {
                // 分段插入，数据量太大引起mysql报错
                int steps = list.size() / 10;
                steps ++;
                int start = 0;
                int end = 0;
                for(int step = 0 ; step < steps; step ++){
                    start = step * 10;
                    end = (step + 1) * 10;
                    if(step == ( steps -1 )){
                        end = list.size();
                    }
                    List<TScSettlebillEntry> subList = list.subList(start, end);
                    if(!CollectionUtils.isEmpty(subList)){
                        tScSettlebillMapper.batchTScSettlebillEntry(subList);
                    }
                }

            }
        }
    }


    /**
     * 保存拆分后的结算单为待开票
     * @param tScSettlebillRequest 结算单
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAsSalInvoice(TScSettlebillRequest tScSettlebillRequest) {
        if(CollectionUtils.isEmpty(tScSettlebillRequest.getTScSettlebillEntryList())){
            throw new ServiceException("待开票的金额，不能小于或等于0");
        }
        if(tScSettlebillRequest.getFee().compareTo(BigDecimal.ZERO) == 0 || tScSettlebillRequest.getFee().compareTo(BigDecimal.ZERO)<0){
            throw new ServiceException("待开票的金额，不能小于或等于0");
        }

        TScSettlebill orgTScSettlebill  = tScSettlebillMapper.selectTScSettlebillById(tScSettlebillRequest.getId());
        if(!orgTScSettlebill.getSettlebillStatus().equals(SettlebillStatus.UNCOMPLETED.getCode())
        ){
            throw new ServiceException("结算单" + orgTScSettlebill.getOrderNo() + "已" + DictUtils.getDictLabel("settlebill_status", orgTScSettlebill.getSettlebillStatus()+""));
        }

        // 待销金额(含税) = 原结算单待销金额(含税) - 本次拆分金额(含税)
        BigDecimal pendingFee = orgTScSettlebill.getPendingFee().subtract(tScSettlebillRequest.getFee()).abs();
        // 0.1元的误差
        if(pendingFee.compareTo(BigDecimal.valueOf(0.1)) > 0){
            throw new ServiceException("待开票的金额，不能大于待销金额");
        }

        // 创建发票对象
        TSalInvoice tSalInvoice = tSalInvoiceService.createTSalInvoiceByTScSettlebill(tScSettlebillRequest);
        // 保存
        tSalInvoiceService.insertTSalInvoice(tSalInvoice);
        logger.info("结算单" + orgTScSettlebill.getOrderNo() + "拆分并生成待开发票，申请单号" + tSalInvoice.getApplyNo());


        /*
            · 拆分后 待销金额 = 0 的结算单标记为 已完成
            · 拆分后 待销金额 > 0 的结算单保持为 待处理，设置已拆分
         */
        TScSettlebill tScSettlebill = new TScSettlebill();
        BeanUtils.copyProperties(tScSettlebillRequest, tScSettlebill);
        if(pendingFee.compareTo(BigDecimal.ZERO) == 0) {
            tScSettlebill.setPendingFee(BigDecimal.ZERO);
            tScSettlebill.setSettlebillStatus(SettlebillStatus.COMPLETED.getCode());
            tScSettlebill.setSettlebillStatusName(SettlebillStatus.COMPLETED.getName());
        }
        if(pendingFee.compareTo(BigDecimal.ZERO) > 0) {
            tScSettlebill.setPendingFee(pendingFee);
            tScSettlebill.setSplitStatus(SplitStatus.SPLIT.getCode());
            tScSettlebill.setSplitStatusName(SplitStatus.SPLIT.getName());
            tScSettlebill.setSettlebillStatus(SettlebillStatus.UNCOMPLETED.getCode());
            tScSettlebill.setSettlebillStatusName(SettlebillStatus.UNCOMPLETED.getName());
        }
        // 提交人
        SysUser user = SecurityUtils.getLoginUser().getUser();
        tScSettlebill.setUpdateBy(user.getUserName());
        tScSettlebill.setUpdateTime(DateUtils.getNowDate());
        // 保存
        tScSettlebillMapper.updateTScSettlebill(tScSettlebill);

        /*
            插入新的可开明细项
            扣减本次拆分的明细，剩余的可开数据另存为 可开明细项
         */
        List<TScSettlebillEntryForinvoice> lastTScSettlebillEntryForinvoiceList = tScSettlebillMapper.selectLastTScSettlebillEntryForinvoiceList(tScSettlebill.getSettleId());
        // 第一次开票时，可开票明细项为空，需要复制原结算的明细
        if(CollectionUtils.isEmpty(lastTScSettlebillEntryForinvoiceList)){
            for(TScSettlebillEntry tScSettlebillEntry : orgTScSettlebill.getTScSettlebillEntryList()){
                TScSettlebillEntryForinvoice tScSettlebillEntryForinvoice = new TScSettlebillEntryForinvoice();
                BeanUtils.copyProperties(tScSettlebillEntry, tScSettlebillEntryForinvoice);
                lastTScSettlebillEntryForinvoiceList.add(tScSettlebillEntryForinvoice);
            }
        }
        // 本次拆分掉的明细
        List<TScSettlebillEntryRequest> tScSettlebillEntryRequestsList = tScSettlebillRequest.getTScSettlebillEntryList();
        // 本次需要保存的可开明细项
        List<TScSettlebillEntryForinvoice> tScSettlebillEntryForinvoiceList = new ArrayList<>();

        for(TScSettlebillEntryForinvoice lastTScSettlebillEntryForinvoice : lastTScSettlebillEntryForinvoiceList){
            for(TScSettlebillEntryRequest tScSettlebillEntryRequest : tScSettlebillEntryRequestsList){
                if(tScSettlebillEntryRequest.getProductCode().equals(lastTScSettlebillEntryForinvoice.getProductCode())){
                    // 该产品若还有剩余待销金额，就生成一个可开明细项
                    if(lastTScSettlebillEntryForinvoice.getAmount().subtract(tScSettlebillEntryRequest.getAmount()).compareTo(BigDecimal.ZERO) > 0){
                        TScSettlebillEntryForinvoice tScSettlebillEntryForinvoice = new TScSettlebillEntryForinvoice();
                        BeanUtils.copyProperties(tScSettlebillEntryRequest, tScSettlebillEntryForinvoice);
                        tScSettlebillEntryForinvoice.setEntryId(IdUtils.simpleUUID());
                        tScSettlebillEntryForinvoice.setSettleId(tScSettlebillRequest.getSettleId());
                        /*
                         计算剩余的值(上次剩余 减去 本次拆分)
                         */
                        // 数量
                        tScSettlebillEntryForinvoice.setQty(lastTScSettlebillEntryForinvoice.getQty().subtract(tScSettlebillEntryRequest.getQty()));
                        // 金额(含税)
                        tScSettlebillEntryForinvoice.setAmount(lastTScSettlebillEntryForinvoice.getAmount().subtract(tScSettlebillEntryRequest.getAmount()));
                        // 金额(不含税)
                        // tScSettlebillEntryForinvoice.setWithoutAmount(lastTScSettlebillEntryForinvoice.getWithoutAmount().subtract(tScSettlebillEntryRequest.getWithoutAmount()));
                        // 折扣金额(不含税)
                        tScSettlebillEntryForinvoice.setDiscountAmount(lastTScSettlebillEntryForinvoice.getDiscountAmount().subtract(tScSettlebillEntryRequest.getDiscountAmount()));
                        // 折扣金额(含税)
                        // tScSettlebillEntryForinvoice.setWithoutDiscountAmount(lastTScSettlebillEntryForinvoice.getWithoutDiscountAmount().subtract(tScSettlebillEntryRequest.getWithoutDiscountAmount()));


                        tScSettlebillEntryForinvoice.setVersion(null);
                        tScSettlebillEntryForinvoice.setCreateBy(user.getUserName());
                        tScSettlebillEntryForinvoice.setCreateTime(DateUtils.getNowDate());
                        tScSettlebillEntryForinvoice.setIsDel(0L);
                        tScSettlebillEntryForinvoiceList.add(tScSettlebillEntryForinvoice);
                    }
                    // 若已经没有剩余金额，就不需要再生成可开明细
                    else {
                        logger.info("结算单{} 物料{} 已经拆分完毕，不会生成可开明细", tScSettlebill.getOrderNo(), tScSettlebillEntryRequest.getProductName());
                    }
                }
            }
        }

        // 将历史可开票明细全部设置为删除(即被该开票单据占用)，版本号为开票单号，方便回退
        Map<String, String> params = new HashMap<>();
        params.put("version", tSalInvoice.getApplyNo());
        params.put("settleId", tScSettlebill.getSettleId());
        tScSettlebillMapper.deleteTScSettlebillEntryForinvoiceBySettleId(params);
        // 插入新的明细
        if(!CollectionUtils.isEmpty(tScSettlebillEntryForinvoiceList)){
            tScSettlebillMapper.batchTScSettlebillEntryForinvoice(tScSettlebillEntryForinvoiceList);
        }
        // 插入结算单和发票对象的关系 t_sc_settle_sal_invoice
        TScSettleSalInvoice tScSettleSalInvoice = new TScSettleSalInvoice();
        tScSettleSalInvoice.setSettleId(tScSettlebill.getSettleId());
        tScSettleSalInvoice.setOrderNo(tScSettlebill.getOrderNo());
        tScSettleSalInvoice.setInvoiceId(tSalInvoice.getInvoiceId());
        tScSettleSalInvoice.setIsDel(0);
        tScSettleSalInvoice.setCreateBy(tSalInvoice.getCreateBy());
        tScSettleSalInvoice.setCreateTime(new Date());
        // 保存
        tScSettleSalInvoiceService.insertTScSettleSalInvoice(tScSettleSalInvoice);
    }


    /**
     * 保存合并后的结算单为待开票
     * @param tScSettlebillRequest 结算单
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAsMergeSalInvoice(TScSettlebillRequest tScSettlebillRequest) {
        // 明细和金额的校验
        if(CollectionUtils.isEmpty(tScSettlebillRequest.getTScSettlebillEntryList())){
            throw new ServiceException("待开票的金额，不能小于或等于0");
        }
        if(tScSettlebillRequest.getFee().compareTo(BigDecimal.ZERO) == 0 || tScSettlebillRequest.getFee().compareTo(BigDecimal.ZERO)<0){
            throw new ServiceException("待开票的金额，不能小于或等于0");
        }
        // FIXME 应改为在redis中获取合并开票的结算单，而不是由前端传回的settleId查询结算单
        // 各个订单的状态校验
        String[] settleIds = tScSettlebillRequest.getSettleId().split(",");
        List<TScSettlebill> tScSettlebillList = new ArrayList<>();
        for(String settleId : settleIds){
            TScSettlebill tScSettlebill = this.selectTScSettlebillBySettleId(settleId);
            if(Objects.isNull(tScSettlebill)){
                throw new ServiceException("结算单[" + settleId + "]不存在");
            }
            if(!tScSettlebill.getSettlebillStatus().equals(SettlebillStatus.UNCOMPLETED.getCode())
            ){
                throw new ServiceException("结算单" + tScSettlebill.getOrderNo() + "已" + DictUtils.getDictLabel("settlebill_status", tScSettlebill.getSettlebillStatus()+""));
            }
            tScSettlebillList.add(tScSettlebill);
        }
        // 创建发票对象
        TSalInvoice tSalInvoice = tSalInvoiceService.createTSalInvoiceByMergeTScSettlebill(tScSettlebillRequest);
        // 保存
        tSalInvoiceService.insertTSalInvoice(tSalInvoice);
        logger.info("结算单集合" + tScSettlebillRequest.getSettleId() + "合并生成待开发票，申请单号" + tSalInvoice.getApplyNo());

        /*
            合并开票会使这批结算单全部金额和明细都生成待开，故无需再插入新的可开票明细，将之前的可开票明细都设置为无效即可
         */
        for(TScSettlebill tScSettlebill : tScSettlebillList){
            tScSettlebill.setMergeIdent(MergeIdent.MERGED.getCode());
            tScSettlebill.setMergeIdentName(MergeIdent.MERGED.getName());
            tScSettlebill.setPendingFee(BigDecimal.ZERO);
            tScSettlebill.setSettlebillStatus(SettlebillStatus.COMPLETED.getCode());
            tScSettlebill.setSettlebillStatusName(SettlebillStatus.COMPLETED.getName());
            // 提交人
            SysUser user = SecurityUtils.getLoginUser().getUser();
            tScSettlebill.setUpdateBy(user.getUserName());
            tScSettlebill.setUpdateTime(DateUtils.getNowDate());
            // 保存
            tScSettlebillMapper.updateTScSettlebill(tScSettlebill);
            // 将历史可开票明细全部设置为删除，版本号为开票单号，方便回退
            Map<String, String> params = new HashMap<>();
            params.put("version", tSalInvoice.getApplyNo());
            params.put("settleId", tScSettlebill.getSettleId());
            tScSettlebillMapper.deleteTScSettlebillEntryForinvoiceBySettleId(params);
            // 插入结算单和发票对象的关系 t_sc_settle_sal_invoice
            TScSettleSalInvoice tScSettleSalInvoice = new TScSettleSalInvoice();
            tScSettleSalInvoice.setSettleId(tScSettlebill.getSettleId());
            tScSettleSalInvoice.setOrderNo(tScSettlebill.getOrderNo());
            tScSettleSalInvoice.setInvoiceId(tSalInvoice.getInvoiceId());
            tScSettleSalInvoice.setIsDel(0);
            tScSettleSalInvoice.setCreateBy(tSalInvoice.getCreateBy());
            tScSettleSalInvoice.setCreateTime(new Date());
            // 保存
            tScSettleSalInvoiceService.insertTScSettleSalInvoice(tScSettleSalInvoice);
        }
    }


    /**
     *
     * @param tScSettlebillList
     */
    @Override
    public void syncSettlebillByErp(List<TScSettlebill> tScSettlebillList) {
        // 默认的销方
        TSysSite sysSite = tSysSiteService.selectDefaultSysSite();
        TScSettlebill tScSettlebillCondition = new TScSettlebill();
        for(TScSettlebill tScSettlebill : tScSettlebillList){
            //invoice_type 调用
            //SELECT dbo.getInvoiceType('ERP发票号InvNum' )
//            String invoiceType = tScSettlebillMapper.getInvoiceTypeByInvNum(tScSettlebill.getOrderNo());
//            String invoiceTypeName = DictUtils.getDictLabel("invoice_type", invoiceType);

            // tScSettlebill.setInvoiceType(invoiceType);
//            tScSettlebill.setInvoiceTypeName(invoiceTypeName);

            tScSettlebillCondition.setOrderNo(tScSettlebill.getOrderNo());
            List<TScSettlebill> scSettlebillList = tScSettlebillMapper.selectTScSettlebillList(tScSettlebillCondition);
            if(!CollectionUtils.isEmpty(scSettlebillList)){
                TScSettlebill orgTScSettlebill = scSettlebillList.get(0);
                long id = orgTScSettlebill.getId();
                String settleId = orgTScSettlebill.getSettleId();
                if(tScSettlebill.getFee() == null){
                    tScSettlebill.setFee(orgTScSettlebill.getFee());
                }
                if(tScSettlebill.getFeeWithoutTax() == null){
                    tScSettlebill.setFee(orgTScSettlebill.getFeeWithoutTax());
                }
                BeanUtils.copyProperties(tScSettlebill, orgTScSettlebill);
                orgTScSettlebill.setId(id);
                orgTScSettlebill.setSettleId(settleId);
                // 明细更新
                List<TScSettlebillEntry> tScSettlebillEntryList = tScSettlebill.getTScSettlebillEntryList();
                for(TScSettlebillEntry tScSettlebillEntry : tScSettlebillEntryList){
                    /*
                        一些字段的处理
                     */
                    // 不含税单价，需要计算含税单价
                    if(tScSettlebill.getIsTax() == IsTax.NOT_TAX.getCode()){
                        //单价(含税) =不含税单价* （1+税率）
                        if(tScSettlebillEntry.getTaxRate() != null){
                            tScSettlebillEntry.setPrice(tScSettlebillEntry.getWithoutPrice().multiply(new BigDecimal(1).add(tScSettlebillEntry.getTaxRate().divide(new BigDecimal(100)))).setScale(8, RoundingMode.HALF_UP));
                            tScSettlebillEntry.setAmount(tScSettlebillEntry.getWithoutAmount().multiply(new BigDecimal(1).add(tScSettlebillEntry.getTaxRate().divide(new BigDecimal(100)))).setScale(8, RoundingMode.HALF_UP));
                        }
                    }
                    // 单价(不含税)为空，则表示接口所传为含税单价，需要计算不含税单价
                    if(tScSettlebill.getIsTax() == IsTax.TAX.getCode()){
                        // 单价(不含税) =含税单价 / （1+税率）
                        if(tScSettlebillEntry.getTaxRate() != null){
                            tScSettlebill.setFeeWithoutTax(tScSettlebill.getFee().divide(new BigDecimal(1).add(tScSettlebillEntry.getTaxRate().divide(new BigDecimal(100)))).setScale(8, RoundingMode.HALF_UP));
                            tScSettlebillEntry.setWithoutAmount(tScSettlebillEntry.getAmount().divide(new BigDecimal(1).add(tScSettlebillEntry.getTaxRate().divide(new BigDecimal(100)))).setScale(8, RoundingMode.HALF_UP));
                        }
                    }
                }
                orgTScSettlebill.setTScSettlebillEntryList(tScSettlebillEntryList);
                orgTScSettlebill.setUpdateBy("erp");
                orgTScSettlebill.setUpdateTime(DateUtils.getNowDate());
                updateTScSettlebillForErp(orgTScSettlebill);
            } else {
                /*
                    一些字段的处理
                 */
                // 购方
                if(!StringUtils.isEmpty(tScSettlebill.getBuyerCode())){
                    TSalBuyer tSalBuyerCondition = new TSalBuyer();
                    tSalBuyerCondition.setBuyerCode(tScSettlebill.getBuyerCode());
                    List<TSalBuyer> tSalBuyerList = tSalBuyerService.selectTSalBuyerList(tSalBuyerCondition);
                    if(!CollectionUtils.isEmpty(tSalBuyerList)){
                        TSalBuyer tSalBuyer = tSalBuyerList.get(0);
                        tScSettlebill.setBuyerName(tSalBuyer.getBuyerName());
                        tScSettlebill.setBuyerCode(tSalBuyer.getBuyerCode());
                        tScSettlebill.setBuyerAccount(tSalBuyer.getBuyerAccount());
                        tScSettlebill.setBuyerAddress(tSalBuyer.getBuyerAddress());
                        tScSettlebill.setBuyerBank(tSalBuyer.getBuyerBank());
                        tScSettlebill.setBuyerNumber(tSalBuyer.getBuyerNumber());
                        tScSettlebill.setBuyerTel(tSalBuyer.getBuyerTel());
                    } else {
                        logger.error("结算单 {}，购方名称 {} 查询不到对应的购方记录", tScSettlebill.getOrderNo(),  tScSettlebill.getBuyerName());
                    }
                } else {
                    logger.error("结算单 {}，购方名称为空", tScSettlebill.getOrderNo());
                }
                // 销方
                tScSettlebill.setSiteCode(sysSite.getSiteCode());
                tScSettlebill.setSiteName(sysSite.getSiteName());
                tScSettlebill.setSellerAccount(sysSite.getAccountNo());
                tScSettlebill.setSellerAddress(sysSite.getAddress());
                tScSettlebill.setSellerBank(sysSite.getBankName());
                tScSettlebill.setSellerName(sysSite.getSiteName());
                tScSettlebill.setSellerNumber(sysSite.getTaxNumber());
                tScSettlebill.setSellerTel(sysSite.getTel());

                // 待销金额
                tScSettlebill.setPendingFee(tScSettlebill.getFee());
                tScSettlebill.setPendingFeeWithoutTax(tScSettlebill.getFeeWithoutTax());
                // 明细更新
                List<TScSettlebillEntry> tScSettlebillEntryList = tScSettlebill.getTScSettlebillEntryList();
                for(TScSettlebillEntry tScSettlebillEntry : tScSettlebillEntryList){
                    /*
                        一些字段的处理
                     */
                    // 不含税单价，需要计算含税单价
                    if(tScSettlebill.getIsTax() == IsTax.NOT_TAX.getCode()){
                        //单价(含税) =不含税单价* （1+税率）
                        if(tScSettlebillEntry.getTaxRate() != null){
                            tScSettlebillEntry.setPrice(tScSettlebillEntry.getWithoutPrice().multiply(new BigDecimal(1).add(tScSettlebillEntry.getTaxRate().divide(new BigDecimal(100)))).setScale(8, RoundingMode.HALF_UP));
                            // TODO  是否先计算 税额

                            tScSettlebillEntry.setAmount(tScSettlebillEntry.getWithoutAmount().multiply(new BigDecimal(1).add(tScSettlebillEntry.getTaxRate().divide(new BigDecimal(100)))).setScale(8, RoundingMode.HALF_UP));
                        }

                    }
                    // 单价(不含税)为空，则表示接口所传为含税单价，需要计算不含税单价
                    if(tScSettlebill.getIsTax() == IsTax.TAX.getCode()){
                        // 单价(不含税) =含税单价 / （1+税率）
                        if(tScSettlebillEntry.getTaxRate() != null){
                            tScSettlebill.setFeeWithoutTax(tScSettlebill.getFee().divide(new BigDecimal(1).add(tScSettlebillEntry.getTaxRate().divide(new BigDecimal(100)))).setScale(8, RoundingMode.HALF_UP));
                            // TODO  是否先计算 税额

                            tScSettlebillEntry.setWithoutAmount(tScSettlebillEntry.getAmount().divide(new BigDecimal(1).add(tScSettlebillEntry.getTaxRate().divide(new BigDecimal(100)))).setScale(8, RoundingMode.HALF_UP));
                        }
                    }
                    // 税额
                    tScSettlebillEntry.setTax(tScSettlebillEntry.getAmount().subtract(tScSettlebillEntry.getWithoutAmount()));
                }
                tScSettlebill.setTScSettlebillEntryList(tScSettlebillEntryList);
                insertTScSettlebill(tScSettlebill);
            }
        }
    }

    /**
     * 结算单开票状态回写同步
     */
    @Override
    public void syncSettlebillWirteBackByErp() {
        // 查询状态为 待同步 的结算单
        TScSettlebill condition = new TScSettlebill();
        condition.setReturnErpStatus(ReturnErpStatus.TOBE.getCode());
        List<TScSettlebill> tScSettlebillList = selectTScSettlebillList(condition);
        //
        logger.info("需要开票状态回写同步的结算单列表长度：{}", tScSettlebillList.size());
        for(TScSettlebill tScSettlebill : tScSettlebillList){
            tScSettlebill.setReturnErpTime(DateUtils.getNowDate());
            try {
                String result = ErpApiUtil.updateSettle(tScSettlebill.getOrderNo(), tScSettlebill.getReturnErpDescription());
                // 解析返回 标记失败或成功
                tScSettlebill.setReturnErpStatus(ReturnErpStatus.FAILED.getCode());
                tScSettlebill.setReturnErpStatusName(ReturnErpStatus.FAILED.getName());
                if(!StringUtils.isEmpty(result)){
                    JSONObject jo = JSON.parseObject(result);
                    if(jo.getInteger("MessageCode").equals(201)){
                        tScSettlebill.setReturnErpStatus(ReturnErpStatus.SUCCESS.getCode());
                        tScSettlebill.setReturnErpStatusName(ReturnErpStatus.SUCCESS.getName());
                    } else {
                        tScSettlebill.setReturnErpDescription(jo.getString("Message"));
                        logger.error("结算单 {} 回写ERP状态失败，原因{}", tScSettlebill.getOrderNo(), jo.getString("Message"));
                    }
                } else {
                    tScSettlebill.setReturnErpDescription("更新接口无响应");
                    logger.error("结算单 {} 回写ERP状态失败，ERP更新接口无响应", tScSettlebill.getOrderNo());
                }
            } catch (Exception e) {
                e.printStackTrace();
                // 标记失败
                tScSettlebill.setReturnErpStatus("0");
                tScSettlebill.setReturnErpStatusName("失败");
                tScSettlebill.setReturnErpDescription(e.getMessage());
            } finally {
                // 更新结算单
                updateTScSettlebillOnly(tScSettlebill);
            }
        }

    }
}
